package com.promise.jokerdream.repository

import com.promise.jokerdream.database.UserDataManager
import com.promise.jokerdream.network.HttpHelper
import com.promise.jokerdream.network.IHttpCallback
import com.promise.jokerdream.network.RetryableHttpCallback
import com.promise.jokerdream.response.pc.BasePCResponse
import com.promise.jokerdream.utils.AppContext
import kotlinx.coroutines.suspendCancellableCoroutine
import kotlinx.serialization.ExperimentalSerializationApi
import kotlinx.serialization.json.Json
import okhttp3.Call
import okhttp3.Response
import java.io.IOException
import kotlin.coroutines.resume

/**
 * 游戏数据仓库
 * 封装所有HTTP请求，提供统一的数据访问接口
 */
class GameRepository {
    
    private val userDataManager by lazy { UserDataManager.getInstance(AppContext.get()) }
    
    companion object {
        @Volatile
        private var INSTANCE: GameRepository? = null
        
        @OptIn(ExperimentalSerializationApi::class)
        val json = Json {
            ignoreUnknownKeys = true // 忽略未知字段
            coerceInputValues = true // 强制输入值
            allowTrailingComma = true
        }
        
        /**
         * 获取GameRepository单例
         */
        fun getInstance(): GameRepository {
            return INSTANCE ?: synchronized(this) {
                INSTANCE ?: GameRepository().also { INSTANCE = it }
            }
        }
    }
    
    /**
     * 获取当前账号的Cookie并合并到请求头中
     */
    private fun mergeHeaders(headers: Map<String, String>?): Map<String, String> {
        val currentAccount = userDataManager.getCurrentAccount()
        val cookieHeader = currentAccount?.cookie
        
        return if (cookieHeader != null && cookieHeader.isNotEmpty()) {
            val mergedHeaders = headers?.toMutableMap() ?: mutableMapOf()
            mergedHeaders["Cookie"] = cookieHeader
            mergedHeaders
        } else {
            headers ?: emptyMap()
        }
    }
    
    /**
     * 通用的GET请求方法
     * @param url 请求URL
     * @param headers 请求头（可选）
     * @param enableRetry 是否启用result=-2时的自动重试，默认为true
     * @param maxRetries 最大重试次数，默认为5次
     * @param retryDelay 重试延迟时间（毫秒），默认为1000ms
     * @return 原始响应字符串
     */
    suspend fun get(
        url: String,
        headers: Map<String, String>? = null,
        enableRetry: Boolean = true,
        maxRetries: Int = 5,
        retryDelay: Long = 1000L
    ): Result<String> {
        // 合并用户Cookie到请求头
        val mergedHeaders = mergeHeaders(headers)
        
        return suspendCancellableCoroutine { continuation ->
            val originalCallback = object : IHttpCallback {
                override fun onSuccess(call: Call, response: Response) {
                    try {
                        val responseBody = response.body?.string()
                        if (responseBody != null) {
                            continuation.resume(Result.success(responseBody))
                        } else {
                            continuation.resume(Result.failure(
                                ApiException(
                                    code = -101,
                                    message = "响应体为空"
                                )
                            ))
                        }
                    } catch (e: Exception) {
                        continuation.resume(Result.failure(
                            ApiException(
                                code = -102,
                                message = "获取响应失败: ${e.message}",
                                cause = e
                            )
                        ))
                    }
                }
                
                override fun onFailure(call: Call, error: IOException) {
                    continuation.resume(Result.failure(
                        ApiException(
                            code = -103,
                            message = "网络请求失败: ${error.message}",
                            cause = error
                        )
                    ))
                }
            }
            
            val callback = if (enableRetry) {
                RetryableHttpCallback(
                    originalCallback = originalCallback,
                    maxRetries = maxRetries,
                    retryDelay = retryDelay,
                    retryRequest = {
                        HttpHelper.get(url, mergedHeaders, originalCallback)
                    }
                )
            } else {
                originalCallback
            }
            
            HttpHelper.get(
                url = url,
                headers = mergedHeaders,
                callback = callback
            )
        }
    }
    
    /**
     * 解析响应并检查结果
     */
    inline fun <reified T : BasePCResponse> parseResponse(responseBody: String): Result<T> {
        return try {
            val parsedResponse = json.decodeFromString<T>(responseBody)
            
            // 检查响应结果
            if (parsedResponse.result == 0) {
                Result.success(parsedResponse)
            } else {
                Result.failure(
                    ApiException(
                        code = parsedResponse.result,
                        message = parsedResponse.msg
                    )
                )
            }
        } catch (e: Exception) {
            Result.failure(
                ApiException(
                    code = -102,
                    message = "解析响应失败: ${e.message}",
                    cause = e
                )
            )
        }
    }
    
}

/**
 * 扩展函数：简化Result的fold操作，自动处理ApiException
 */
inline fun <T, R> Result<T>.foldWithApiException(
    onSuccess: (value: T) -> R,
    onFailure: (code: Int, msg: String) -> R
): R {
    return this.fold(
        onSuccess = onSuccess,
        onFailure = { exception ->
            when (exception) {
                is ApiException -> onFailure(exception.code, exception.message)
                else -> onFailure(-101, exception.message ?: "未知错误")
            }
        }
    )
}

/**
 * 扩展函数：简化API调用，只需要传入responseClass
 */
suspend inline fun <reified T : BasePCResponse> GameRepository.getAndParse(url: String): Result<T> {
    return get(url).fold(
        onSuccess = { responseBody ->
            parseResponse<T>(responseBody)
        },
        onFailure = { exception ->
            Result.failure(exception)
        }
    )
}

/**
 * API异常类
 */
data class ApiException(
    val code: Int,
    override val message: String,
    override val cause: Throwable? = null
) : Exception(message, cause)
